package com.xsq.wifi.utils;

import android.util.Log;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Timer;
import java.util.TimerTask;

public class PersistentConnection {
    private static final String TAG = "PersistentConnection";
    private static final int TIMEOUT_MS = 5000;
    private static final int DEVICE_PORT = 3333;
    private static final byte PROTOCOL_VERSION = 0x01;
    private static final short PCP_STA_OK = 0x0001;

    private Socket socket;
    private String deviceIp;
    private volatile boolean isConnected;

    // 单例模式（可选）
    private static class Holder {
        static final PersistentConnection INSTANCE = new PersistentConnection();
    }
    public static PersistentConnection getInstance() {
        return Holder.INSTANCE;
    }

    /**
     * 建立长连接
     */
    public synchronized void connect(String deviceIp) throws IOException {
        if (isConnected && socket != null && !socket.isClosed()) {
            return;
        }

        this.deviceIp = deviceIp;
        closeSocket(socket); // 确保旧连接关闭

        socket = new Socket();
        socket.connect(new InetSocketAddress(deviceIp, DEVICE_PORT), TIMEOUT_MS);
        socket.setSoTimeout(TIMEOUT_MS);
        socket.setKeepAlive(true); // 启用TCP Keep-Alive
        isConnected = true;

        Log.d(TAG, "Connected to " + deviceIp);
    }

    /**
     * 发送请求（复用长连接）
     */
    public synchronized Response sendRequest(byte cmd, byte[] payload) throws IOException {
        // 增加连接有效性检查
        if (!isConnected || socket == null || socket.isClosed() || !socket.isConnected()) {
            connect(deviceIp); // 强制重建连接
        }

        try {
            // 构造请求
            ByteBuffer requestBuffer = ByteBuffer.allocate(8 + (payload != null ? payload.length : 0));
            requestBuffer.order(ByteOrder.LITTLE_ENDIAN);
            requestBuffer.put(PROTOCOL_VERSION);
            requestBuffer.put(cmd);
            requestBuffer.putShort((short) 0x0000); // 控制字段
            requestBuffer.putInt(payload != null ? payload.length : 0);
            if (payload != null) {
                requestBuffer.put(payload);
            }

            // 发送请求
            OutputStream out = socket.getOutputStream();
            out.write(requestBuffer.array());
            out.flush();

            // 接收响应
            byte[] header = readExactly(socket.getInputStream(), 8);
            ByteOrder responseOrder = detectByteOrder(header);
            ByteBuffer headerBuffer = ByteBuffer.wrap(header).order(responseOrder);

            byte version = headerBuffer.get();
            byte responseCmd = headerBuffer.get();
            short status = headerBuffer.getShort();
            int dataLength = headerBuffer.getInt();

            // 校验协议
            if (version != PROTOCOL_VERSION || responseCmd != cmd) {
                throw new IOException("Protocol mismatch");
            }
            if (status != PCP_STA_OK) {
                throw new IOException("Device error: 0x" + Integer.toHexString(status & 0xFFFF));
            }

            // 读取数据
            byte[] data = dataLength > 0 ? readExactly(socket.getInputStream(), dataLength) : new byte[0];
            return new Response(version, responseCmd, status, data, responseOrder);

        } catch (IOException e) {
            isConnected = false;
            closeSocket(socket);
            Log.e(TAG, "Request failed, will retry: " + e.getMessage());
            throw e;
        }
    }


    /**
     * 关闭连接
     */
    public synchronized void disconnect() {
        closeSocket(socket);
        isConnected = false;
        Log.d(TAG, "Disconnected");
    }

    /**
     * 安全关闭Socket
     */
    private void closeSocket(Socket socket) {
        if (socket != null) {
            try {
                socket.close();
            } catch (IOException e) {
                Log.e(TAG, "Close socket error", e);
            }
        }
    }

    /**
     * 从流中精确读取指定长度的数据
     */
    private byte[] readExactly(InputStream in, int length) throws IOException {
        byte[] data = new byte[length];
        int offset = 0;
        while (offset < length) {
            int read = in.read(data, offset, length - offset);
            if (read == -1) throw new IOException("Unexpected EOF");
            offset += read;
        }
        return data;
    }

    /**
     * 检测响应字节序
     */
    private ByteOrder detectByteOrder(byte[] header) {
        // 根据协议约定判断（示例：假设第0字节为标志位）
        return (header[0] == 0x01) ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN;
    }

    /**
     * 响应数据封装
     */
    public static class Response {
        public final byte version;
        public final byte cmd;
        public final short status;
        public final byte[] data;
        public final ByteOrder order;

        public Response(byte version, byte cmd, short status, byte[] data, ByteOrder order) {
            this.version = version;
            this.cmd = cmd;
            this.status = status;
            this.data = data;
            this.order = order;
        }
    }
}